home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / rcs56.zoo / rcs / src / osystem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-08  |  4.5 KB  |  215 lines

  1. /*
  2.  * system(): execute a command, passed as a string
  3.  *
  4.  * Written by Eric R. Smith and placed in the public domain.
  5.  *
  6.  * Modified by Allan Pratt to call _unx2dos on redirect file names
  7.  * and to call spawnvp() without calling fork() -- why bother?
  8.  *
  9.  * Modified by Frank Ridderbusch in _parseargs() to handle the case
  10.  * >'file'. Without the modification, the quotes would end up in the
  11.  * filename for redirection
  12.  *
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18. #include <stdlib.h>
  19. #include <process.h>
  20. #include <errno.h>
  21. #include <file.h>
  22. #include <osbind.h>
  23.  
  24. #ifdef DEBUG
  25. #define MSG(x) Cconws(x "\r\n")
  26. #define MSG2(x,y) printf(x,y);
  27. #else
  28. #define MSG(x)
  29. #define MSG2(x,y)
  30. #endif
  31.  
  32. #define isquote(c) ((c) == '\"' || (c) == '\'' || (c) == '`')
  33. #define ARG_ERR       ( (Argentry *) -1 )
  34.  
  35. /* struct. used to build a list of arguments for the command */
  36.  
  37. typedef struct argentry {
  38.     struct argentry *next;
  39.     char    string[1];
  40. } Argentry;
  41.  
  42.  
  43. /* allocate an Argentry that will hold the string "s" */
  44.  
  45. static Argentry *_argalloc(s)
  46.     const char *s;
  47. {
  48.     Argentry *x;
  49.  
  50.     x = (Argentry *) malloc((size_t)(sizeof(Argentry) + strlen(s) + 1));
  51.     if (!x)
  52.         return ARG_ERR;
  53.     x->next = (Argentry *) 0;
  54.     strcpy(x->string, s);
  55.     return x;
  56. }
  57.  
  58. /* free a list of Argentries */
  59.  
  60. static void _argfree(p)
  61.     Argentry *p;
  62. {
  63.     Argentry *oldp;
  64.  
  65.     while (p) {
  66.         oldp = p;
  67.         p = p->next;
  68.         free(oldp);
  69.     }
  70. }
  71.  
  72. /* parse a string into a list of Argentries. Words are defined to be
  73.  * (1) any sequence of non-blank characters
  74.  * (2) any sequence of characters starting with a ', ", or ` and ending
  75.  *     with the same character. These quotes are stripped off.
  76.  * (3) any spaces after an unquoted > or < are skipped, so
  77.  *     "ls > junk" is parsed as 'ls' '>junk'.
  78.  */
  79.  
  80. static Argentry *_parseargs(s)
  81.     const char *s;
  82. {
  83.     Argentry *cur, *res;
  84.     char buf[FILENAME_MAX];
  85.     char *t, quote;
  86.  
  87.     res = cur = _argalloc("");
  88.  
  89.     for(;;) {
  90.         t = buf;
  91. again:
  92.         while (isspace(*s)) s++;
  93.         if (!*s) break;
  94.         if (isquote(*s)) {
  95.             quote = *s++;
  96.             while (*s && *s != quote)
  97.                 *t++ = *s++;
  98.             if (*s) s++;    /* skip final quote */
  99.         }
  100.         else {
  101.             while (*s && (!isspace(*s))) {
  102.                 *t++ = *s++;
  103.                 if (isquote(*s))
  104.                     goto again;
  105.             }
  106.             if (*s && ( *(s-1) == '>' || *(s-1) == '<' ))
  107.                 goto again;
  108.         }
  109.         *t = 0;
  110.         cur->next = _argalloc(buf);
  111.         if (!(cur = cur->next))      /* couldn't alloc() */
  112.             return ARG_ERR;
  113.     }
  114.     cur->next = (Argentry *) 0;
  115.     cur = res; res = res->next; free(cur);
  116.     return res;
  117. }
  118.  
  119.  
  120. /* Here is system() itself.
  121.  * FIXME: we probably should do I/O redirection and wildcard expansion.
  122.  * also, should errno get set here??
  123.  */
  124.  
  125. static int retval;
  126.  
  127. int system(s)
  128.     const char *s;
  129. {
  130.     Argentry *al, *cur;
  131.     char **argv, *p;
  132.     int  argc, i;
  133.     char *infile, *outfile;
  134.     int  infd, outfd, append = 0;
  135.     int oldin, oldout;    /* hold the Fdup'd in, out */
  136.     char path[FILENAME_MAX];
  137.  
  138.     if (!s)        /* check for system() supported ?? */
  139.         return 1;
  140.     al = _parseargs(s);        /* get a list of args */
  141.     if (al == ARG_ERR)        /* not enough memory */
  142.         return (errno = ENOMEM);
  143.  
  144.     infile = outfile = "";
  145. MSG("in system");
  146.  
  147. /* convert the list returned by _parseargs to the normal char *argv[] */
  148.     argc = i = 0;
  149.     for (cur = al; cur; cur = cur->next)
  150.         argc++;
  151.     if (!(argv = (char **) malloc((size_t)(argc * sizeof(char *)))))
  152.         return (errno = ENOMEM);
  153.     for (cur = al; cur; cur = cur->next) {
  154.         p = cur->string;
  155.         if (*p == '>') {
  156. MSG("redirecting output");
  157.             outfile = p+1;
  158.             if (*outfile == '>') {
  159.                 outfile++;
  160.                 append = 1;
  161.             }
  162.             else
  163.             append = 0;
  164.         }
  165.         else if (*p == '<') {
  166. MSG("redirecting input");
  167.             infile = p+1;
  168.         }
  169.         else
  170.             argv[i++] = p;
  171.     }
  172.      argv[i] = (char *)0;
  173.  
  174. /* now actually run the program */
  175.     /* there was a "vfork" call here, but why bother? */
  176.     if (*infile) {
  177.         _unx2dos(infile,path);
  178.         infd = Fopen(path, 0);
  179.         if (infd < __SMALLEST_VALID_HANDLE) {
  180.             perror(infile);
  181.             _exit(2);
  182.         }
  183.         oldin = Fdup(0);
  184.         Fforce(0, infd);
  185.     }
  186.     if (*outfile) {
  187.         _unx2dos(outfile,path);
  188. MSG2("outfile=%s\n",outfile);
  189. MSG2("path=%s\n",path);
  190.         if (append) {
  191.             outfd = Fopen(path, 2);
  192.             if (outfd < __SMALLEST_VALID_HANDLE)
  193.                 outfd = Fcreate(path, 0);
  194.             else
  195.                 Fseek(0L, outfd, 2);
  196.         }
  197.         else
  198.             outfd = Fcreate(path, 0);
  199.         if (outfd < __SMALLEST_VALID_HANDLE) {
  200.             perror(outfile);
  201.             _exit(2);
  202.         }
  203.         oldout = Fdup(1);
  204.         Fforce(1, outfd);
  205.     }
  206. MSG("Calling spawnvp");
  207.     retval = spawnvp(P_WAIT, argv[0], argv);
  208. MSG("Exiting");
  209.     if (*infile) Fforce(0,oldin), Fclose(oldin), Fclose(infd);
  210.     if (*outfile) Fforce(1,oldout), Fclose(oldout), Fclose(outfd);
  211.     free(argv);
  212.     _argfree(al);
  213.     return retval;
  214. }
  215.